import {
  BreakOrContext,
  MethodAfterAdvice,
  MethodAfterReturningAdvice,
  MethodAfterThrowingAdvice,
  MethodAroundAdvice,
  MethodBeforeAdvice
} from '../common';
import { AdviceType, Aspect } from './aspect';

/** 方法前置增强，空实现 */
@Aspect({type: AdviceType.MethodBeforeAdvice})
export class NoOpMethodBeforeAdvice implements MethodBeforeAdvice {
  order: number = Number.MIN_VALUE;

  filterPointcut(target: any, property: PropertyKey, argsOrValue?: any): boolean {
    return false;
  }

  before(target: any, method: PropertyKey, args: any[]): void {
  }
}

/** 方法正常执行后的后置增强，空实现 */
@Aspect({type: AdviceType.MethodAfterReturningAdvice})
export class NoOpMethodAfterReturningAdvice implements MethodAfterReturningAdvice {
  order: number = Number.MIN_VALUE;

  filterPointcut(target: any, property: PropertyKey, argsOrValue?: any): boolean {
    return false;
  }

  afterReturning(target: any, method: PropertyKey, args: any[], returnValue: any): void {
  }
}

/** 方法执行异常时的后置增强，空实现 */
@Aspect({type: AdviceType.MethodAfterThrowingAdvice})
export class NoOpMethodAfterThrowingAdvice implements MethodAfterThrowingAdvice {
  order: number = Number.MIN_VALUE;

  filterPointcut(target: any, property: PropertyKey, argsOrValue?: any): boolean {
    return false;
  }

  afterThrowing(target: any, method: PropertyKey, args: any[], error: any): void {
  }
}

/** 方法执行完成之后的增强(无论方法执行是否发生异常)，空实现 */
@Aspect({type: AdviceType.MethodAfterAdvice})
export class NoOpMethodAfterAdvice implements MethodAfterAdvice {
  order: number = Number.MIN_VALUE;

  filterPointcut(target: any, property: PropertyKey, argsOrValue?: any): boolean {
    return false;
  }

  after(target: any, method: PropertyKey, args: any[], successful: boolean, returnValue?: any, error?: any): void {
  }
}

/** 方法执行前后的环绕增强，空实现 */
@Aspect({type: AdviceType.MethodAroundAdvice})
export class NoOpMethodAroundAdvice implements MethodAroundAdvice {
  order: number = Number.MIN_VALUE;

  filterPointcut(target: any, property: PropertyKey, argsOrValue?: any): boolean {
    return false;
  }

  before(target: any, method: PropertyKey, args: any[]): BreakOrContext {
    return {isReturn: false};
  }

  after(target: any, method: PropertyKey, args: any[], successful: boolean, returnValue?: any, error?: any, aroundContext?: any): false | void {
  }
}
